const AD_CLASS_NAME = 'CLASS42bc4e2f_b826_11e9_9ed0_18dbf2568723'; //UUID

function getCurrentScript() {
  //currentScript: IE不支持，Chrome、Firefox支持；
  if (document.currentScript) {
    return document.currentScript;
  }
  
  if (document.scripts.length == 0) {
    return null;
  }
  
  //readyState: IE支持(IE11不支持)，Chrome、Firefox不支持
  if (document.scripts[0].readyState) {
    for (var i = 0; i < document.scripts.length; i++) {
      if (document.scripts[i].readyState === 'interactive') {
        return document.scripts[i];
      }
    }    
  }

  //IE11: 本方法不适用动态放入广告代码而导致位置非数组最后一个的情形（如：insertBefore），
  //      同时，如果使用insertBefore等方式动态加入<script>节点，其中的代码有可能不会自动执行。
  return document.scripts[document.scripts.length - 1];
}

function ad(slotId, node) {
  var baseUrl = function(){
    var scripts = document.getElementsByClassName(AD_CLASS_NAME);
    var i = scripts[0].src.toLowerCase().lastIndexOf('/js/');
    return scripts[0].src.substring(0, i);
  }();
  
  String.prototype.format = function () {
    var values = arguments;
    return this.replace(/\{(\d+)\}/g, function (match, index) {
        return (values.length > index) ? values[index] : "";
      });
  }

  var xhr = getXhr();
  xhr.onreadystatechange = function(){
    if (xhr.readyState==4 && xhr.status==200) {
      var data = JSON.parse(xhr.responseText);
      var slot = data.data.slot, ads = data.data.ads;

      switch(slot.type) {
        case 1: //嵌入
          makeEmbed(slot, ads, node); 
          break;
        case 2: //漂浮
          makeFloat(slot, ads, node);
          break;
        case 3: //弹窗
          makePopup(slot, ads, node);
          break;
        case 4: //漂移
          makeDrift(slot, ads, node);
          break;
      }
    }
  }
  
  xhr.open('GET', '{0}/slot/ads?id={1}'.format(baseUrl, slotId), true);
  xhr.send();
 
  //后面皆为函数：

  function makeEmbed(slot, ads, node) {
    makeAdShow(slot, ads, node, 'position:relative;');
  }

  function makeFloat(slot, ads, node){
    makeAdShow(slot, ads, node, 
      'position:{0}; {1}:{2}px; {3}:{4}px;'
        .format((slot.scrolled==1) ? 'absolute':'fixed', slot.align_h, slot.margin_h, slot.align_v, slot.margin_v));
  }

  function makePopup(slot, ads, node){
    var cookieName  = AD_CLASS_NAME + '-POPUP' + slot.id;
    var showCount = getCounter(cookieName);
    if (showCount > 0) {
      refreshCounterExpires(cookieName, slot.day_times); 
    }  
    
    //day_times==0: 不限次，不进行计数
    if (slot.day_times > 0) {
      if (showCount >= slot.day_times) {
        return;
      }
      incCounter(cookieName, slot.day_times);
    } 

    var styleH = (slot.align_h == 'center') ?
      'left:{0}px'.format(window.innerWidth/2 - slot.width/2) :
      '{0}:{1}px'.format(slot.align_h, slot.margin_h);

    var styleV = (slot.align_v == 'center') ?
      'top:{0}px'.format(window.innerHeight/2 - slot.height/2) :
      '{0}:{1}px'.format(slot.align_v, slot.margin_v);

    makeAdShow(slot, ads, node, 
      'z-index:100; display:block; position:absolute;  {0}; {1}; background:rgba(36, 36, 36, 0.7); '
        .format(styleH, styleV));
  }

  function makeDrift(slot, ads, node){
    var _slot = makeAdShow(slot, ads, node, 'position:absolute; left:50px; top:50px;');
    
    var x = 50, y = 60;
    var xin = true, yin = true;
    var step = 1;
    var delay = 10;
    var flag = setInterval(_drift, delay);

    _slot.onmouseover = function() {
      clearInterval(flag);
    }

    _slot.onmouseout = function() {
      flag = setInterval(_drift, delay);
    }

    function _drift() {
      var L = T = 0;
      var R = document.documentElement.clientWidth - _slot.offsetWidth;
      var B = document.documentElement.clientHeight - _slot.offsetHeight;
      _slot.style.left = (x + document.body.scrollLeft || document.documentElement.scrollLeft) + "px";
      _slot.style.top = (y + document.body.scrollTop || document.documentElement.scrollTop) + "px";
      x = x + step * (xin ? 1 : -1);
      if (x < L) {
        xin = true;
        x = L;
      }
      if (x > R) {
        xin = false;
        x = R;
      }
      
      y = y + step * (yin ? 1 : -1);
      if (y < T) {
        yin = true;
        y = T;
      }
      if (y > B) {
        yin = false;
        y = B;
      }
    }
  }

  function makeAdShow(slot, ads, node, slotStyle) {
    //每个广告（实例）动态分配一个UUID ：因为广告位可能会重复出现（如每几行插入一条广告的情况），不能用广告位Id或硬编码值，
    var id = 'AD' + getUuid();
    var doc = (node.nodeName=='IFRAME') ? node.contentDocument : document;

    var _slot = doc.createElement('div');
    _slot.id = id;
    _slot.className = AD_CLASS_NAME;
  
    if (node.nodeName=='IFRAME') {
      doc.getElementsByTagName("body")[0].appendChild(_slot);
    }
    else {
      node.parentNode.insertBefore(_slot, node); 
    }

    if (!slot || ads.length == 0) {
      _slot.style = 'width:100%; height:100%; display:flex; align-content:center; flex-wrap:wrap;';
      _slot.innerHTML = '<p style="text-align:center; width:100%">' + ((!slot) ? '此广告位未注册！' : '此广告位未投放广告！') + '</p>';   
      return;
    }

    var _content = doc.createElement('ul');
    _content.className = "content";
    _slot.appendChild(_content);
  
    var style = doc.createElement('style');
    style.type = 'text/css';
    style.innerHTML = '\
      #{0}, #{0} * {margin: 0; padding: 0;} \
      #{0} {width:{1}px; height:{2}px; margin:0px auto; overflow:hidden; {4}} \
      #{0} .content {width:{1}px; height:{2}px; list-style:none; position:absolute; top:0; left:0;} \
      #{0} .content li {display:none; position:absolute; top:0px; left:0px;} \
      #{0} .content li.current {display:block; position:absolute; top:0px; left:0px;} \
      #{0} .content li img {float: left;} \
      #{0} .indexbar {position:absolute; bottom:10px; left:150px; list-style:none;} \
      #{0} .indexbar li {margin-left:10px; float:left;} \
      #{0} .indexbar li div {width:12px; height:12px; background:#DDDDDD; border-radius:6px; cursor:pointer;} \
      #{0} .indexbar li div.current {width:12px; height:12px; background:#A10000; border-radius:6px; cursor:pointer;} \
      #{0} .prev {width:40px; height:63px; background:url({3}/images/icons.png) 0px 0px; position:absolute; top:205px; left:10px;z-index: 120;} \
      #{0} .next {width:40px; height:63px; background:url({3}/images/icons.png) -40px 0px; position:absolute; top:205px; right:10px; z-index: 120;} \
      #{0} .prev:hover {background:url({3}/images/icons.png) 0px -62px;} \
      #{0} .next:hover {background:url({3}/images/icons.png) -40px -62px;} \
      #{0} .close {z-index:120; position:relative; width:30px; height:30px; float:right; text-align:center; font-size:24px; cursor:pointer; color:#333; background:#fff;} \
      #{0} .close:hover, #{0} .close:focus {z-index:120; color:white; background:red; cursor:pointer;}'.format(id, slot.width, slot.height, baseUrl, slotStyle);
    doc.getElementsByTagName("head")[0].appendChild(style);

    var hasFlashAd = false;
    for(var i = 0; i < ads.length; i++){
      var w = (!ads[i].width) ? slot.width : ads[i].width, 
          h = (!ads[i].height) ? slot.height : ads[i].height;

      var _li = doc.createElement('li');
      _content.appendChild(_li);
        
      var s;
      switch(ads[i].type) {
        case 1: //文字
          s = '<a href="{0}" target="{1}" style="{2}">{3}</a>';
          _li.innerHTML = s.format(getLogClickUrl(ads[i].put_id, ads[i].click_url), ads[i].target_window, ads[i].style, ads[i].content);
          break;
        case 2: //图片
          var filePath = (ads[i].file_source_type == 1) ? baseUrl + '/adfile/' + ads[i].content : ads[i].content;

          s = '<a href="{0}" target="{1}"><img src="{2}" width="{3}" height="{4}"></a>';
          _li.innerHTML = s.format(getLogClickUrl(ads[i].put_id, ads[i].click_url), ads[i].target_window, filePath, w, h);
          break;
        case 3: //flash
          var filePath = (ads[i].file_source_type == 1) ? baseUrl + '/adfile/' + ads[i].content : ads[i].content;

          hasFlashAd = true;
          s =  
            '<div>' + 
              '<object width="{3}" height="{4}" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=7,0,19,0">' +
                '<param name="movie" value="{2}">' +
                '<param name="quality" value="high">' +
                '<param name="wmode" value="transparent">' +
                '<embed width="{3}" height="{4}" src="{2}" quality="high" pluginspage="http://www.macromedia.com/go/getflashplayer" type="application/x-shockwave-flash">' +
                '</embed>' +
              '</object>' +
            '</div>';
          
          if (ads[i].click_countable == 1) {
            s = s + 
              '<div style="position:absolute; left:0px; top:0px; z-index:110; filter:alpha(opacity=0)">' +
                '<a href="{0}" target="{1}">' +
                  '<img src="{5}/images/transparent.gif" width="{3}" height="{4}" />' +
                '</a>' +
              '</div>';	 
          }
          s = '<div class="flash-main">' + s + '</div>';
          s = s.format(getLogClickUrl(ads[i].put_id, ads[i].click_url), ads[i].target_window, filePath, w, h, baseUrl);

          var s2 = '';
          if (ads[i].content_ext != '') {
            var s2 = '<div class="flash-alter" style="display:none;"><a href="{0}" target="{1}"><img data-src="{2}" width="{3}" height="{4}"></a></div>';
            var filePath2 = (ads[i].file_source_type == 1) ? baseUrl + '/adfile/' + ads[i].content_ext : ads[i].content_ext;
            s2 = s2.format(getLogClickUrl(ads[i].put_id, ads[i].click_url), ads[i].target_window, filePath2, w, h)
          }
          
          _li.innerHTML = '<div class="flash">' + s + s2 + '</div>';
          break;
        case 4: //富媒体：可能有加载执行的script
          //使用iframe的原因：DOM创建<script>，不会执行其中脚本，所以：iframe + write
          var _iframe = doc.createElement('iframe');
          _iframe.width = String(w);
          _iframe.height = String(h);
          _iframe.frameBorder =  _iframe.marginWidth = _iframe.marginHeight = "0";
          _iframe.scrolling = "no";
          _li.appendChild(_iframe);

          var r = ads[i].content;
          var es = JSON.parse(ads[i].content_ext);
          for(var j = 0; j < es.length; j++) {
            var v = (es[j].type == 2 && es[j].source == 1) ? baseUrl + '/adfile/' + es[j].cvalue : es[j].cvalue;
            r = r.replace(es[j].cname, v);
            
            v = getLogClickUrl(ads[i].put_id, es[j].lvalue); //不管“是否统计点击”设置
            r = r.replace(es[j].lname, v);
          }
          
          var d = _iframe.contentDocument; //此时iframe应应加入DOM，否则contentDocument为null
          d.write('<div>' + r + '</div>');//加<div>的原因：Write <scirpt>会被放到head中。
          d.close();
          break;
        case 5: //外部广告位代码：一般为加载执行的script
          //使用iframe的原因：DOM创建<script>，不会执行其中脚本，所以：iframe + write
          var _iframe = doc.createElement('iframe');
          _iframe.width = String(w);
          _iframe.height = String(h);
          _iframe.frameBorder =  _iframe.marginWidth = _iframe.marginHeight = "0";
          _iframe.scrolling = "no";
          _li.appendChild(_iframe);

          var d = _iframe.contentDocument; //此时iframe应应加入DOM，否则contentDocument为null
          d.write('<div>' + ads[i].content + '</div>');//加<div>的原因：Write <scirpt>会被放到head中。
          d.close();
          break;
      }
    }

    if (hasFlashAd) {
      initFlash(_slot);
    }
    
    var _ads = _content.children; 
    _ads[0].classList.add('current');

    if (ads.length > 1) {
      var _indexbar = doc.createElement('ul');
      _indexbar.className = "indexbar";
      _slot.appendChild(_indexbar);
  
      s = '';
      for (var i = 0; i < ads.length; i++){
        s = s + '<li><div></div></li>';
      }
      _indexbar.innerHTML = s;
      
      var _indexs = _indexbar.getElementsByTagName('div');
      _indexs[0].classList.add('current');

      var _prev = doc.createElement('div');
      _prev.className = "prev";
      _slot.appendChild(_prev);

      var _next = doc.createElement('div');
      _next.className = "next";
      _slot.appendChild(_next);
    }

    if (slot.closable == 1) {
      var _close = doc.createElement('span');
      _close.className = "close";
      _close.innerHTML = "&times;";
      _close.onclick = closeShow;
      _slot.appendChild(_close);
    }
  
    if (_ads.length > 1) {
      setRotate(slot, _content, _ads, _indexs, _prev, _next);
    }

    //自动关闭
    if (slot.stay_time != 0) {
      setInterval(closeShow, slot.stay_time * 1000);
    }
  
    logShow(ads);
    return _slot;

    function closeShow() {
      _slot.style.display = 'none';
    }

  }

  function initFlash(node){
    var flashEnabled = getCookie('flashEnabled');
    
    //Chrome：允许flash时，flash运行询问前flashChecker()返回无效。
    //Firefox：允许flash时，flash运行询问前flashChecker()就返回有效；询问按钮在flash控件上。
    //edge: 允许flash时，flash运行询问前flashChecker()返回无效。
    //IE11: 允许flash时，flashChecker()返回有效; 无flash运行询问。
    //为了Firefox，不能对flash统计点击量（那样flash会被透明图片覆盖）！
    if (!flashChecker().f) {
      applyAlter(node);
    }
    else if (flashEnabled != '1') {
      flashEnabled =  '1';
      setCookie('flashEnabled', flashEnabled);  
    }

    if (flashEnabled == '') {
      flashEnabled =  '?';
      setCookie('flashEnabled', flashEnabled);  
      
      //触发询问是否允许Flash的对话框；对话框完成前，后续代码继续执行。
      //但是，对话框完成后，timer会失效；并会再次进入initFlash()（cfm：不明所以！）
      //所以，timer第二次进入initFlash()时设置！
      //
      //兼容性：
      //  Chrome：允许flash时询问，禁用时地址栏标注；
      //  Firefox：允许flash打开页面，禁用时打开页面；
      //  edge：允许flash时询问，禁用时打开页面
      //  IE11：允许flash（“ActiveX筛选”未勾选）时打开页面，禁用时打开页面。
      //  如果打开了adobe页面，回退或重新进入flash页面即可。
      window.location.href = "http://get.adobe.com/cn/flashplayer/";
    }
    else if (flashEnabled == '?') {
      var timer = setInterval(checkFlashEnabled(), 1000);

      setTimeout(
        function(){
          clearInterval(timer);
          timer = setInterval(checkFlashEnabled(), 3000);
        }, 5000); //5秒钟后降频

      function checkFlashEnabled(){
        if (flashChecker().f) {
          clearInterval(timer);
          setCookie('flashEnabled', '1');
          applyMain(node);
        }
      }
    }

    function applyMain(node) {
      var list = node.ownerDocument.querySelectorAll('.{0} .flash'.format(AD_CLASS_NAME));
      for(var i = 0; i < list.length; i++) {
        var nodes = list[i].childNodes;
        for(var j = 0; j < nodes.length; j++) {
          nodes[j].style.display = (nodes[j].className == 'flash-main') ?  'block' : 'none';  
        }
      }
    }

    function applyAlter(node) {
      var list = node.querySelectorAll('.{0} .flash-alter img'.format(AD_CLASS_NAME));
      for(var i = 0; i < list.length; i++) {
          list[i].src = list[i].getAttribute('data-src');
      }

      list = node.ownerDocument.querySelectorAll('.{0} .flash'.format(AD_CLASS_NAME));
      for(var i = 0; i < list.length; i++) {
        var nodes = list[i].childNodes;
        for(var j = 0; j < nodes.length; j++) {
          nodes[j].style.display = (nodes[j].className == 'flash-main' && nodes.length == 2) ?  'none' : 'block';
        }
      }
    }
  }


  function setRotate(slot, _content, _ads, _indexs, _prev, _next) {
    var current = 0;
    
    _indexs[0].classList.add('current');

    for(var i = 0; i < _indexs.length; i++) {
      _indexs[i].index = i;

      _indexs[i].onmouseover = function() {
        if(current == this.index) return;
        current = this.index;
        rotate();
      }
    }

    _prev.onclick = function() {
      current--;
      if(current == -1){
        current = _indexs.length - 1;
      }
      rotate();
    }
    
    _next.onclick = function() {
      current++;
      if(current == _indexs.length) {
        current = 0;
      }
      rotate();
    }
    
    var rotateTimer  = setInterval(_next.onclick, slot.rotate_interval * 1000);

    _content.onmouseover = function() {
        clearInterval(rotateTimer);
    }
    
    _content.onmouseout = function() {
      rotateTimer = setInterval(_next.onclick, slot.rotate_interval * 1000);
    }
    
    function rotate() {
      for(var i = 0; i < _ads.length; i++){
        _ads[i].classList.remove('current');
        _indexs[i].classList.remove('current');
      }

      _ads[current].style.opacity = 0;
      _ads[current].style.filter = "alpha(opacity=0)";
      _ads[current].classList.add('current');
      _indexs[current].classList.add('current');
      fadeIn(_ads[current]);
    }
  }

  //【待改进】如果一获取及视为show一次，则可以放Server.getAds时记录！
  function logShow(ads){
    var ids = new Array();
    for(var i = 0, len=ads.length; i < len; i++){
      ids[i] = ads[i].put_id;
    }
    var data = JSON.stringify({fromUrl:document.URL, putIds: JSON.stringify(ids)});

    var xhr = getXhr();
    xhr.open('POST', '{0}/show/log'.format(baseUrl), true);
    xhr.setRequestHeader('content-type', 'application/json');
    xhr.send(data);
  }


  function getLogClickUrl(putId, clickUrl){
    return '{0}/click/log?putId={1}&clickUrl={2}&fromUrl={3}'
      .format(baseUrl, putId, encodeURIComponent(clickUrl), encodeURIComponent(document.URL));
  }


  //淡入：可用CSS3代替
  function fadeIn(obj){
    var alpha=0;
    clearInterval(timer);
    var timer=setInterval(function(){
      alpha++;
      obj.style.opacity=alpha/100;
      obj.style.filter="alpha(opacity="+alpha+")";
      if(alpha==100) {
        clearInterval(timer);
      }
    }, 10);
  }


  //淡出：可用CSS3代替
  function fadeOut(obj){
    var alpha=obj.style.opacity * 100;
    clearInterval(timer);
    var timer=setInterval(function(){
      alpha--;
      obj.style.opacity=alpha/100;
      obj.style.filter="alpha(opacity="+alpha+")";
      if(alpha==0) {
        clearInterval(timer);
      }
    }, 10);
  }


  function getXhr() {
    var xmlhttp;
    if (window.XMLHttpRequest)
    {// code for IE7+, Firefox, Chrome, Opera, Safari
        xmlhttp=new XMLHttpRequest();
    }
    else
    {// code for IE6, IE5
        xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
    }
    return xmlhttp;
  }

  //refer: <https://www.cnblogs.com/zoex/p/javascript-string-format.html>
  //refer: node.js string-format <https://blog.csdn.net/chendeyou5/article/details/79449535>
  function getUuid() {
    var d = new Date().getTime();
    var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, 
        function(c) {
          var r = (d + Math.random()*16)%16 | 0;
          d = Math.floor(d/16);
          return (c=='x' ? r : (r&0x3|0x8)).toString(16);
        });
    return uuid;
  };


  function getCounter(cname) {
    var value = getCookie(cname);
    if (value != "") {
      value = JSON.parse(value);
      return Number(value.count);
    }
    else {
      return 0;
    }
  }


  function incCounter(cname, dtimes) {
    if (dtimes == 0) {
      return;
    }

    var exdate;
    var value = getCookie(cname);
    if (value == "") {
      var exdays = (dtimes >= 1) ? 1 : 1 / dtimes;
      exdate = new Date();
      exdate.setTime(exdate.getTime() + (exdays*24*60*60*1000));

      value = {count: 1, expires: exdate};
    } 
    else {
      value = JSON.parse(value);
      value.count = Number(value.count) + 1;
      exdate = new Date(value.expires);
    }  
    setCookie(cname, JSON.stringify(value), exdate); 
  }


  //根据一天显示次数dtimes，刷新到期时间：
  //如果dtimes变大，到期提前，则使用新的到期
  function refreshCounterExpires(cname, dtimes){
    var exdate = new Date();
    if (dtimes > 0) {
      var exdays = (dtimes >= 1) ? 1 : 1 / dtimes;
      exdate.setTime(exdate.getTime() + (exdays*24*60*60*1000));
    }

    var value = getCookie(cname);
    if (value != "") {  
      value = JSON.parse(value);

      var exdate_old = new Date(value.expires);
      if (exdate < exdate_old) { 
        value.expires = exdate;
        setCookie(cname, JSON.stringify(value), exdate); 
      }
    }
  }


  function setCookie(cname, cvalue, exdate){
    var expires = (exdate) ? "; expires=" + exdate.toUTCString() : "";
    document.cookie = cname + "=" + encodeURIComponent(cvalue) + expires;
  }

  function getCookie(cname){
    var name = cname + "=";
    var ca = document.cookie.split(';');
    for(var i = 0; i < ca.length; i++) {
        var c = ca[i].trim();
        if (c.indexOf(name)==0) { 
          return decodeURIComponent(c.substring(name.length,c.length)); 
        }
    }
    return "";
  }

  function flashChecker() {
    var hasFlash = 0; 
    var flashVersion = 0;  
    
    if(document.all) {
      var swf = new ActiveXObject('ShockwaveFlash.ShockwaveFlash');
      if(swf) {
        hasFlash = 1;
        VSwf = swf.GetVariable("$version");
        flashVersion = parseInt(VSwf.split(" ")[1].split(",")[0]);
      }
    } else {
      if(navigator.plugins && navigator.plugins.length > 0) {
        var swf = navigator.plugins["Shockwave Flash"];
        if(swf) {
          hasFlash = 1;
          var words = swf.description.split(" ");
          for(var i = 0; i < words.length; ++i) {
            if(isNaN(parseInt(words[i]))) continue;
            flashVersion = parseInt(words[i]);
          }
        }
      }
    }
    return { f: hasFlash, v: flashVersion };
  }

}